iT邦幫忙

2024 iThome 鐵人賽

DAY 23
1
DevOps

全端監控技術筆記---從Sentry到Opentelemetry系列 第 23

Day23--簡單demo看看 Opentelemetry log data + Loki + Grafana

  • 分享至 

  • xImage
  •  

前言

前面幾篇我們demo過 Opentelemetry 三本柱中的 tracemetric,今天我們來demo一下最後的 log 資料,讓整個觀測性更加完善。

NodeJS + Opentelemetry log setting

必要依賴

除了之前的@opentelemetry/sdk-node@opentelemetry/auto-instrumentations-node,我們還需要 @opentelemetry/exporter-logs-otlp-http 來導出日誌資料。

NodeJS Log Library

在 Node.js 應用中,傳統的日誌處理方式通常是透過一些常見的日誌庫來實現,如 WinstonBunyanPino等等,它們都支持JSON格式的日誌,同時也將日誌分級。

而在 Opentelemetry SDK 使用函數getNodeAutoInstrumentations時,也會自動引入相關的庫: @opentelemetry/instrumentation-bunyan@opentelemetry/instrumentation-pino@opentelemetry/instrumentation-winston來覆蓋該日誌依賴的使用,使其與 OpenTelemetry 無縫集成。

本次demo,我們就先使用 Bunyan 這個日誌依賴:

const bunyan = require('bunyan');

const logger = bunyan.createLogger({
    name: 'node-demo-service',
});

module.exports = {
    logger,
};

OpenTelemetry sdk 設置

接下來,除了呼叫getNodeAutoInstrumentations來自動引入相關的庫,再來就是將 log exporter 寫入sdk:

const logExporter = new OTLPLogExporter({
    url: 'http://localhost:4318/v1/logs', // 指向你的本地 OTLP Collector
});

const otelSdk = new NodeSDK({
    logRecordProcessor: logExporter,
    resource,
    instrumentations: [getNodeAutoInstrumentations()],
});

otelSdk.start();

其中,http://localhost:4318/v1/logs是本地 opentelemetry collector 的endpoint。

opentelemtry-collector

現在我們才聊到 opentelemetry collector,是因為之前的 tracing data 和 metric data 在opentelemtry sdk中、都可以直接 export 給相關的服務;但目前我看到的 log service 都沒辦法直接接收 opentelemetry 蒐集的 log data,所以必須透過 opentelemetry collecter 來整理和轉發 logs data。

我們透過docker compose 來運行本地的 opentelemetry collecter。首先,新增一個設定檔otel-collector-config.yaml:

receivers:
    otlp:
        protocols:
            grpc:
            http:
                endpoint: '0.0.0.0:4318'

exporters:
    loki:
        endpoint: 'http://self-loki:3100/loki/api/v1/push'

service:
    pipelines:
        logs:
            receivers: [otlp]
            exporters: [loki]

在這裡,我們使用 Loki 來作為日誌存儲服務,OpenTelemetry Collector 將接收日誌並轉發至 Loki。

而 docker-compose 中,設定 opentelemetry-collector:

    self-otel-collector:
        container_name: self-otel-collector
        image: otel/opentelemetry-collector-contrib:latest
        command: ['--config=/etc/otel-collector-config.yaml']
        volumes:
            - ./config/otel-collector-config.yaml:/etc/otel-collector-config.yaml
        ports:
            - '4317:4317' # OTLP gRPC 接口
            - '4318:4318' # OTLP HTTP 接口
        depends_on:
            - self-loki
        networks:
            - otel-network

我們把 opentelemetry collector 的 HTTP endpoint定義為 http://localhost:4318,要跟我們node sdk中設定的一致,才能傳送正確。

Loki 和 Grafana

Loki

Loki 是由 Grafana Labs 開發的高擴展性日誌聚合系統,類似於 Prometheus 處理指標的方式,Loki 以最小的索引處理並查詢日誌數據。

我們要在本地運行它,也可以透過 docker-compose的方式,不過先定義下設定檔loki-local-config.yaml

auth_enabled: false

server:
    http_listen_port: 3100

common:
    instance_addr: 0.0.0.0
    path_prefix: /loki
    storage:
        filesystem:
            chunks_directory: /loki/chunks
            rules_directory: /loki/rules
    replication_factor: 1
    ring:
        kvstore:
            store: inmemory

schema_config:
    configs:
        - from: 2020-10-24
          store: tsdb
          object_store: filesystem
          schema: v13
          index:
              prefix: index_
              period: 24h

ruler:
    alertmanager_url: http://localhost:9093

透過docker-compose 運行後,可以透過

curl -s "http://localhost:3100/loki/api/v1/label" | jq .

來查看Loki服務能否接收到logs,如果可以的話會回傳一個 success response:

{
  "status": "success"
}

Grafana

Grafana 是一個強大的可視化工具,可以接入不同的數據源、將數據可視化。我們今天就是利用 Grafana 來連接 Loki 服務、獲取並展示logs data。

  • grafana docker-compose setting:
grafana:
    image: grafana/grafana:latest
    environment:
        - GF_SECURITY_ADMIN_PASSWORD=admin
    ports:
        - '3080:3000' # Grafana Web UI
    depends_on:
        - self-loki
    networks:
        - otel-network
  • 運行過後,在 datasouce 介面中新增對 Loki 數據源的連線

image
新增 loki 數據源

image
在docker compose 中定義的 loki url

運行demo

回到我們NodeJS應用,新增一個api來寫入log:

app.get('/demo', async (req, res) => {
    logger.info('start /demo api');
    await sleep(1500);
    logger.warn('wair for a while');
    await sleep(1800);
    logger.warn('wair a little bit longer');
    await sleep(2000);
    logger.info('success');
    res.json({ message: 'hello nodejs opentelemetry' });
});app.get('/demo', async (req, res) => {
    logger.info('start /demo api');
    await sleep(1500);
    logger.warn('wair for a while');
    await sleep(1800);
    logger.warn('wair a little bit longer');
    await sleep(2000);
    logger.info('success');
    res.json({ message: 'hello nodejs opentelemetry' });
});

呼叫該 api 後,我們可以在 Grafana 介面上查看結果

image

小結

本次的 demo 展示了如何在 NodeJS 應用中設置 OpenTelemetry 日誌,並通過 OpenTelemetry Collector 將日誌導出到 Loki,最終使用 Grafana 來可視化日誌數據。

本次demo可以在此 Github repository上查看。

ref

ChangeLog

  • 20241007--補上圖片
  • 20240927--初稿

上一篇
Day22--手寫一個獲取 metric data 的 SDK
下一篇
Day24---手寫一個獲取 log data 的 SDK
系列文
全端監控技術筆記---從Sentry到Opentelemetry30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言